﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace THO7AlgoritmTimerApplication
{
    class Median3x3List : VisionAlgorithm
    {
        public Median3x3List(String name) : base(name) { }
        private List<byte> RedList;
        private List<byte> GreenList;
        private List<byte> BlueList;


        public override System.Drawing.Bitmap DoAlgorithm(System.Drawing.Bitmap sourceImage)
        {

            Rectangle rect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height);
            Bitmap returnImage = (Bitmap)sourceImage.Clone();

            BitmapData srcData = sourceImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData desData = returnImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);






            int stride = srcData.Stride;
            int nOffset = stride - sourceImage.Width * 3;
            System.IntPtr Scan0 = srcData.Scan0;
            System.IntPtr DesScan0 = desData.Scan0;

            unsafe
            {
                byte* p = (byte*)(void*)Scan0;
                byte* DesP = (byte*)(void*)DesScan0;

                p += stride;
                DesP += stride;
                for (int y = 1; y < sourceImage.Height - 1; ++y)
                {
                    p += 3;

                    DesP += 3;
                    for (int x = 1; x < sourceImage.Width - 1; ++x)
                    {
                        RedList = new List<byte>();
                        GreenList = new List<byte>();
                        BlueList = new List<byte>();
                        getList(p, 3, stride, nOffset);
                        RedList.Sort();
                        BlueList.Sort();
                        GreenList.Sort();



                        DesP[0] = BlueList[4];
                        DesP[1] = GreenList[4];
                        DesP[2] = RedList[4];


                        p += 3;
                        DesP += 3;


                    }


                    p += nOffset;
                    DesP += nOffset;

                }
            }
            returnImage.UnlockBits(desData);
            sourceImage.UnlockBits(srcData);
            return returnImage;
        }

        private unsafe void getList(byte* p, int size, int stride, int nOffset)
        {


           
            int tempSize = ((size) - 1) / 2;
            p -= tempSize * 3;
            p -= tempSize * stride;
            int count = 0;

            for (int y = -tempSize; y <= tempSize; ++y)
            {
                for (int x = -tempSize; x <= tempSize; ++x)
                {
                    BlueList.Add(p[0]);
                    RedList.Add(p[2]);
                    GreenList.Add(p[1]);
                    p += 3;
                    count++;

                }

                p += nOffset;

            }
            p -= tempSize * 3;
            p -= tempSize * stride;


           
        }

        private static void quicksort(byte[] items, int left, int right)
        {

            int i, j;
            byte x, y;

            i = left; j = right;
            x = items[(left + right) / 2];

            do
            {
                while ((items[i] < x) && (i < right)) i++;
                while ((x < items[j]) && (j > left)) j--;

                if (i <= j)
                {
                    y = items[i];
                    items[i] = items[j];
                    items[j] = y;
                    i++; j--;
                }
            } while (i <= j);

            if (left < j) quicksort(items, left, j);
            if (i < right) quicksort(items, i, right);



        }

    }
}